home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2001 December / pcwk12201b.iso / Wersje pelne i specjalne / Ghostscript 7.0 / gs700w32.exe / gs7.00 / lib / pdf_font.ps < prev    next >
Text File  |  2000-12-25  |  26KB  |  786 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of AFPL Ghostscript.
  3. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  4. % distributor accepts any responsibility for the consequences of using it, or
  5. % for whether it serves any particular purpose or works at all, unless he or
  6. % she says so in writing.  Refer to the Aladdin Free Public License (the
  7. % "License") for full details.
  8. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. % in a plain ASCII text file named PUBLIC.  The License grants you the right
  10. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. % conditions described in the License.  Among other things, the License
  12. % requires that the copyright notice and this notice be preserved on all
  13. % copies.
  14.  
  15. % $Id: pdf_font.ps,v 1.18 2000/12/26 04:29:30 alexcher Exp $
  16. % pdf_font.ps
  17. % PDF font operations.
  18.  
  19. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  20. .currentglobal true .setglobal
  21. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  22. GS_PDF_ProcSet begin
  23. pdfdict begin
  24.  
  25. % We cache the PostScript font in an additional element of the
  26. % font resource dictionary, called PSFont.
  27.  
  28. % ---------------- Encodings ---------------- %
  29.  
  30. % Apply a list of differences to an Encoding.
  31. % Note that the differences may cause the array to grow.
  32. /updateencoding {    % <encoding> <differences> updateencoding <enc'>
  33.     % Calculate the length of the result.
  34.   exch 0 2 index {
  35.     dup type /nametype ne { exch pop } { pop 1 add } ifelse
  36.   } forall
  37.   1 index length .max array dup 0 4 -1 roll putinterval
  38.   exch 0 exch {
  39.         % Stack: enc' code element
  40.     dup type /nametype ne
  41.       { exch pop }
  42.       { 3 copy put pop 1 add }
  43.     ifelse
  44.   } forall pop
  45. } bdef
  46.  
  47. % Get the Encoding for a font.
  48. /getencoding        % <base-encoding> <font-resource> getencoding <enc>
  49.  { /Encoding knownoget
  50.     { dup type /nametype eq
  51.        {
  52.          % The published PDF specification says the Encoding name
  53.          % "must be" one of the 3 predefined Encodings, implying
  54.          % that an error should occur if it isn't.  However, Acrobat
  55.          % Reader simply ignores unknown names, and since there are
  56.          % some buggy applications that rely on this, we do the same.
  57.  
  58.          dup dup dup /MacRomanEncoding eq
  59.          exch /MacExpertEncoding eq or 
  60.          exch /WinAnsiEncoding eq or
  61.            { exch pop findencoding
  62.            }
  63.            { pop
  64.            }
  65.          ifelse
  66.        }
  67.        { dup /BaseEncoding knownoget
  68.       { findencoding 3 -1 roll pop exch
  69.       }
  70.      if
  71.      /Differences knownoget { updateencoding } if
  72.        }
  73.       ifelse
  74.     }
  75.    if
  76.  } bdef
  77.  
  78. % Rename a font with a generated name.
  79. /renamefont {        % <fontdict> renamefont <font'>
  80.   dup /FontName 2 copy get genfontname dup 5 1 roll put definefont
  81. } bind def
  82.  
  83. % Adjust a font according to the Encoding and Widths in the font resource.
  84. /adjustfont {        % <font-resource> <font> adjustfont <font'>
  85.   getfontencoding
  86.   getfontmetrics 4 -1 roll pop .updatefont { renamefont } if
  87. } bind def
  88.  
  89. % Get the (possibly modified) encoding of a font.
  90. /getfontencoding {    % <font-resource> <font> getfontencoding
  91.             %   <font-resource> <font> <Encoding|null>
  92.   1 index /Encoding known {
  93.     dup /Encoding .knownget { 2 index getencoding } { null } ifelse
  94.   } {
  95.     null
  96.   } ifelse
  97. } bdef
  98.  
  99. % Get the metrics of a font, if specified.
  100. /getfontmetrics {    % <font-resource> <font> <Encoding|null> getfontmetrics
  101.             %   <font-resource> <font> <Encoding|null>
  102.             %   <Metrics|null>
  103.   2 index /Widths known {
  104.     dup null eq { pop dup /Encoding get } if
  105.     4 dict begin
  106.       /Encoding exch def
  107.       /Metrics Encoding length dict def
  108.       exch
  109.       dup /Widths oget /Widths exch def
  110.         % Stack: font font-res
  111.         % Note that widths are always based on a 1000-unit
  112.         % character space, but the FontMatrix may specify
  113.         % some other scale factor.  Compensate for this here,
  114.         % by scaling the Widths if necessary.
  115.       0.001 2 index /FontMatrix get 0 get div
  116.         % Stack: font font-res mscale
  117.       1 index /FirstChar oget dup 1 4 index /LastChar oget
  118.        {    % Stack: font font-res mscale first-char index
  119.      Encoding 1 index get
  120.      Widths 2 index 4 index sub oget
  121.          % Stack: font font-res mscale first-char index charname width
  122.      4 index mul
  123.         % There is a hack here to deal with encodings where the
  124.         % same character appears more than once, because the Metrics
  125.         % dictionary works by character name, not by character code.
  126.         % Because of this, we can't deal with Width vectors that
  127.         % specify different widths for the same character name
  128.         % appearing multiple times in the Encoding.
  129.      Metrics 2 index .knownget not { 0 } if 0 ne {
  130.        pop pop
  131.      } {
  132.         % Work around a bug in pdfTeX, which can generate Encoding
  133.         % vectors containing nulls.
  134.        1 index null ne {
  135.          Metrics 3 1 roll put
  136.        } {
  137.          pop pop
  138.        } ifelse
  139.      }
  140.      ifelse pop
  141.        }
  142.       for pop
  143.         % Now fill in the MissingWidth for any encoded characters
  144.         % that aren't in Metrics already.  Note that built-in
  145.         % fonts may have Widths/FirstChar/LastChar but no
  146.         % FontDescriptor, so we must check for this.
  147.         % Stack: font font-res mscale
  148.       1 index /FontDescriptor knownoget {
  149.     Metrics exch
  150.     /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  151.     Encoding {
  152.         % Stack: font font-res mscale missing-width metrics charname
  153.         % Work around the abovementioned pdfTeX bug.
  154.       dup null ne {
  155.         2 copy known not { 2 copy 4 index put } if pop
  156.       } {
  157.         pop
  158.       } ifelse
  159.     } forall pop pop pop
  160.       } {
  161.     pop
  162.       } ifelse
  163.     exch Encoding Metrics end
  164.   } {
  165.     null
  166.   } ifelse
  167. } bdef
  168.  
  169. % ---------------- Descriptors ---------------- %
  170.  
  171. % Partial descriptors for the 14 built-in fonts.  Note that
  172. % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
  173. % object has undergone a subtle change in its meaning which has serious
  174. % consequences for searching with Acrobat:
  175. % In PDF 1.1, the flag meant: Font has StandardEncoding
  176. % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
  177. /standardfontdescriptors mark
  178.   /Courier mark /Flags 16#23 .dicttomark
  179.   /Courier-Oblique 1 index
  180.   /Courier-Bold 1 index
  181.   /Courier-BoldOblique 1 index
  182.   /Helvetica mark /Flags 16#20 .dicttomark
  183.   /Helvetica-Oblique 1 index
  184.   /Helvetica-Bold 1 index
  185.   /Helvetica-BoldOblique 1 index
  186.   /Times-Roman mark /Flags 16#22 .dicttomark
  187.   /Times-Bold 1 index
  188.   /Times-Italic mark /Flags 16#62 .dicttomark
  189.   /Times-BoldItalic 1 index
  190.   /Symbol mark /Flags 16#4 .dicttomark
  191.   /ZapfDingbats 1 index
  192. .dicttomark readonly def
  193.  
  194. % ---------------- Utilities ---------------- %
  195.  
  196. % Fabricate a font name by adding ?'s on the end.
  197. /genfontname        % <name> genfontname <name>
  198.  { dup length string cvs
  199.     { (?) concatstrings
  200.       dup cvn FontDirectory exch known not { cvn exit } if
  201.     }
  202.    loop
  203.  } bdef
  204.  
  205. % Find a font, and adjust its encoding if necessary.
  206. /.pdfdfndict mark
  207.   /defaultfontname /Helvetica
  208. .dicttomark readonly def
  209. /pdffindfont {        % <font-resource> <fontname> pdffindfont <font>
  210.         % If the font isn't available, synthesize one based on
  211.         % its descriptor.
  212.   dup /Font resourcestatus {
  213.     pop pop findfont
  214.   } {
  215.     1 index /FontDescriptor knownoget {
  216.         % Stack: font-res fontname fontdesc
  217.       dup /Flags oget
  218.       dup 16#40 and -6 bitshift        % 1, oblique/italic
  219.       1 index 16#40000 and -17 bitshift add    % 2, bold
  220.       exch 16#2 and 2 bitshift add    % 8, serif
  221.         % We should look at the fixed flag, too.
  222.         % Stack: font-res fontname fontdesc properties
  223.       1 index /FontName oget exch
  224.         % Analyzes font name and extract "Narrow" property
  225.         % which is not described by the FontDescriptor Flags.
  226.       0 2 index .fontnameproperties 4 and or
  227.         % Rebind the default font name to Helvetica so that
  228.         % fonts with no properties are handled correctly.
  229.       //.pdfdfndict begin .substitutefontname end
  230.         % Stack: font-res fontname fontdesc substname|null
  231.       Fontmap 1 index known not {
  232.         % No available good substitution, use the standard one.
  233.     pop 1 index .substitutefont
  234.       } if
  235.       QUIET not {
  236.     (Substituting font ) print dup =only
  237.     ( for ) print 2 index =only (.) = flush
  238.       } if
  239.       3 -1 roll pop findfont
  240.         % Stack: font-res fontdesc font
  241.         % If this is a small-caps font, replace the CharString
  242.         % entries for a..z.
  243.       exch /Flags oget 16#20000 and 0 ne {
  244.     true .copyfontdict
  245.     dup /CharStrings 2 copy get dup length dict .copydict
  246.     4 index /FirstChar get 97 .max
  247.     5 index /LastChar get 122 .min 1 exch {
  248.         % Stack: font-res font' font' /CharStrings charstrings code
  249.         % Note that this only remaps a-z, not accented characters.
  250.       5 index /Widths oget 1 index 7 index /FirstChar get sub oget
  251.       1 string dup 0 5 -1 roll put
  252.         % Stack: font-res font' font' /CharStrings charstrings code
  253.         %   width (x)
  254.       2 index exch dup cvn exch
  255.       dup 0 2 copy get 32 sub put 4 -1 roll {
  256.             % Stack: operand (X) width
  257.         0 setcharwidth exch pop
  258.         currentfont /FontMatrix get matrix invertmatrix concat
  259.         0.7 dup scale 0 0 moveto show
  260.       } /exec cvx 4 packedarray cvx put
  261.     } for put
  262.     renamefont
  263.       } if
  264.     } {
  265.         % No descriptor available, use the default algorithm.
  266.       findfont
  267.     } ifelse
  268.   } ifelse adjustfont
  269. } bdef
  270.  
  271. % ---------------- Type 1 fonts ---------------- %
  272.  
  273. /buildType1        % <Type1-font-resource> buildType1 <font>
  274.  { dup /BaseFont get pdffindfont
  275.  } bdef
  276.  
  277. % The state dictionary for the embedded Type 1 font reading procedure
  278. % has the following keys and values:
  279. %    data - stream (filter)
  280. %    buffer, buffer2 - string
  281. %    hexify - procedure to convert buffer to hex if needed
  282. %    leftstr - string containing (non-negative) integer
  283. %    sectionstr - string containing a character 0 .. 2
  284. %    stream - (stream) dictionary
  285. %    proc - procedure of the form {-dict- type1read}
  286. % When the procedure is executing, this dictionary is current.
  287. % leftstr and sectionstr are strings so that we can change their values
  288. % reliably in case the font executes a restore!
  289. % We also have to do something special about embedded fonts that
  290. % execute definefont more than once -- that is the function of topFontDict.
  291.  
  292. % Read an embedded Type 1 font.
  293. /readfontfilter {    % <proc> readfontfilter <filter>
  294.   0 () /SubFileDecode filter
  295. } bdef
  296. /readtype1dict 5 dict dup begin
  297.   /definefont {
  298.     dup topFontDict eq topFontDict null eq or {
  299.       dup wcheck not { dup length dict copy } if
  300.       exch pop savedFontName exch
  301.     } if
  302.     //systemdict /definefont get exec
  303.   } bdef
  304.   /eexec {
  305.         % Assume the font dictionary is on the top of the stack.
  306.     count 0 gt { /topFontDict 1 index cvlit store } if
  307.     55665 /eexecDecode filter
  308.     //systemdict begin readtype1dictcopy begin cvx stopped
  309.     currentdict readtype1dictcopy eq { end } if
  310.     currentdict //systemdict eq { end } if
  311.      { stop } if
  312.   } bdef
  313. end readonly def
  314. /readtype1 {        % <font-resource> <stream-dict> readtype1 <font>
  315.         % Read the definition, using a procedure-based filter
  316.         % that turns binary/hex conversion on and off
  317.         % at the right times.
  318.    1 index exch
  319.    PDFfile fileposition 3 1 roll
  320.    10 dict begin
  321.      /leftstr (          ) 10 string copy def
  322.        dup /Length1 oget leftstr cvs pop
  323.      /sectionstr <00> 1 string copy def
  324.      /stream 1 index def
  325.      true resolvestream /data exch def
  326.      /buffer 1000 string def        % arbitrary
  327.      /buffer2 buffer length 2.1 div cvi 1 sub string def
  328.      /hexify /buf2hex load def
  329.    currentdict end
  330.    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  331.    readfontfilter
  332.         % Some buggy embedded fonts leave extra junk on the stack,
  333.         % so we have to make a closure that records the stack depth
  334.         % in a fail-safe way.
  335.    //systemdict begin
  336.         % The PDF specification is somewhat muddy about whether
  337.         % an embedded font's name is supposed to be the BaseFont
  338.         % from the Font object or the FontName from the descriptor.
  339.         % Acrobat Distiller requires the former.  Save away the
  340.         % name so we can substitute it at definefont time.
  341.    //readtype1dict dup length 3 add dict copy begin
  342.    1 index /BaseFont oget /savedFontName exch def
  343.    /topFontDict null def
  344.    /readtype1dictcopy currentdict def
  345.     { run } aload pop count 1 sub 2 packedarray cvx exec
  346.    end end
  347.    count exch sub { pop } repeat
  348.    PDFfile 3 -1 roll setfileposition
  349.    /BaseFont oget findfont
  350.    adjustfont
  351.  } bdef
  352.  
  353. % Execute the appropriate reading procedure.
  354. /type1read        % <dict> type1read <string>
  355.  { begin leftstr cvi
  356.     { type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  357.    (          ) leftstr copy cvs pop end
  358.  } bdef
  359.  
  360. % Read the next block of data into the buffer.
  361. /type1readdata        % <left> <buffer> type1readdata <substring> <left'>
  362.  { 0 2 index 2 index length min getinterval
  363.         % Adobe requires readstring to signal an error if given
  364.         % an empty string.  Work around this nonsense here.
  365.    dup length 0 ne { data exch readstring pop } if
  366.    dup length 3 -1 roll exch sub
  367.    DEBUG
  368.     { dup =only ( read ) print
  369.       1 index length =only (: ) print
  370.       1 index == flush
  371.     } if
  372.  } bdef
  373.  
  374. % Read the next block of the initial text portion.
  375. /type1read1 {        % <left> type1read1 <string> <left'>
  376.   DEBUG { (read1 ) print } if
  377.   dup 0 eq {
  378.     pop sectionstr 0 1 put
  379.     stream /Length2 oget
  380.             % Determine whether to hexify data for eexec.
  381.     dup 8 lt {
  382.       type1read2    % Hexify.
  383.     } {
  384.       DEBUG { (read2 ) print } if
  385.       buffer2 type1readdata exch
  386.             % The check doesn't have to be 100% accurate:
  387.             % hexifying is always OK.
  388.       dup 0 8 getinterval 0 exch { or } forall
  389.       128 ge {
  390.     /hexify { } store
  391.     /buffer2 buffer def    % We don't need an intermediate buffer.
  392.       } if hexify exch
  393.     } ifelse
  394.   } {
  395.     buffer type1readdata
  396.   } ifelse
  397. } bdef
  398.  
  399. % Convert a string from binary to hex for eexec.
  400. % Free variables: buffer.
  401. /buf2hex {        % <string> buf2hex <hexstring>
  402.   buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  403.   buffer (>) search pop exch pop exch pop
  404. } bdef
  405.  
  406. % Read the next block of the encrypted portion.
  407. /type1trailer
  408. (0000000000000000000000000000000000000000000000000000000000000000\n\
  409. 0000000000000000000000000000000000000000000000000000000000000000\n\
  410. 0000000000000000000000000000000000000000000000000000000000000000\n\
  411. 0000000000000000000000000000000000000000000000000000000000000000\n\
  412. 0000000000000000000000000000000000000000000000000000000000000000\n\
  413. 0000000000000000000000000000000000000000000000000000000000000000\n\
  414. 0000000000000000000000000000000000000000000000000000000000000000\n\
  415. 0000000000000000000000000000000000000000000000000000000000000000\n\
  416. cleartomark\n)
  417. readonly def
  418. /type1read2 {        % <left> type1read2 <string> <left'>
  419.   DEBUG { (read2 ) print } if
  420.    dup 0 eq
  421.     { pop sectionstr 0 2 put
  422.       stream /Length3 oget
  423.       dup 0 eq
  424.        { DEBUG { (trailer ) print } if
  425.      type1trailer exch
  426.        }
  427.        { type1read3
  428.        }
  429.       ifelse
  430.     }
  431.     { buffer2 type1readdata exch hexify exch
  432.     }
  433.    ifelse
  434. } bdef
  435.  
  436. % Read the next block of the final text portion.
  437. % When finished, this procedure returns an empty string.
  438. /type1read3        % <left> type1read3 <string> <left'>
  439.  { DEBUG { (read3 ) print } if
  440.    buffer type1readdata
  441.  } bdef
  442.  
  443. % ---------------- Type 3 fonts ---------------- %
  444.  
  445. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  446.  
  447. /buildType3 {        % <Type3-font-resource> buildType3 <font>
  448.   8 dict begin
  449.     /FontType 3 def
  450.     /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
  451.     /FontBBox 1 index /FontBBox get cvx def
  452.     /FontMatrix 1 index /FontMatrix oget def
  453.     /CharProcs 1 index /CharProcs oget def
  454.     1 index /Widths knownoget {
  455.       /Widths exch def
  456.       /FirstChar 1 index /FirstChar oget def
  457.       /LastChar 1 index /LastChar oget def
  458.     } if
  459.     /FontName 1 index /Name get genfontname def
  460.     /Encoding .notdefEncoding 2 index getencoding def
  461.         % We have to define BuildChar rather than BuildGlyph:
  462.         % there is no PDF equivalent of glyphshow, and we need
  463.         % the character code to access the Widths.
  464.     /BuildChar {
  465.         % Stack: font charcode
  466.       1 index begin 3 dict begin
  467.       /Font 3 -1 roll def /CharCode 1 index def
  468.       Encoding exch get CharProcs exch oget
  469.       PDFfile fileposition exch
  470.       false resolvestream
  471.         % Stack: filepos stream
  472.         % Don't let setgcolor set the color inside the BuildGlyph
  473.         % procedure, because this causes an /undefined error.
  474.       q null /FillColor gput null /StrokeColor gput
  475.       Font /Resources get exch pdfopdict .pdfruncontext
  476.       Q
  477.       PDFfile exch setfileposition
  478.       end end
  479.     } bdef
  480.     FontName currentdict end definefont exch pop
  481. } bdef
  482. /.adjustcharwidth {    % <wx> <wy> .adjustcharwidth <wx'> <wy'>
  483.   /Widths where {
  484.     begin
  485.     CharCode FirstChar ge CharCode LastChar le and {
  486.       exch pop Widths CharCode FirstChar sub get exch
  487.     } if end
  488.   } if
  489. } bdef
  490.  
  491. % ---------------- TrueType fonts ---------------- %
  492.  
  493. /TTfonts mark
  494.   /Arial /Helvetica
  495.   /Arial,Italic /Helvetica-Oblique
  496.   /Arial,Bold /Helvetica-Bold
  497.   /Arial,BoldItalic /Helvetica-BoldOblique
  498.   /CourierNew /Courier
  499.   /CourierNew,Bold /Courier-Bold
  500.   /TimesNewRoman /Times-Roman
  501.   /TimesNewRoman,Italic /Times-Italic
  502.   /TimesNewRoman,Bold /Times-Bold
  503.   /TimesNewRoman,BoldItalic /Times-BoldItalic
  504. .dicttomark readonly def
  505.  
  506. /buildTrueType {    % <TrueType-font-resource> buildTrueType <font>
  507.   dup /BaseFont get
  508.   dup TTfonts exch .knownget {
  509.     exch pop
  510.         % Hack required by the PDF specification: if the
  511.         % font resource has Subtype = /TrueType but the actual
  512.         % (installed) font is not a TrueType font, ignore the
  513.         % Encoding in the font resource.  However, all current
  514.         % versions of Acrobat Reader have the 14 base TrueType
  515.         % fonts built in, so this produces incorrect output for
  516.         % badly designed PDF files that specify these file names
  517.         % with /Subtype = /TrueType but no embedded definition.
  518.         % Compensate for this by removing the /Subtype key when
  519.         % looking up the font.
  520.     exch dup length dict copy dup /Subtype null put exch
  521.   } if pdffindfont
  522. } bdef
  523.  
  524. % Read an embedded TrueType font.
  525. /readtruetype {        % <font-resource> <stream-dict> readtruetype <font>
  526.         % This is much simpler than readtype1, because we don't
  527.         % have to deal with the tripartite .PFB format.
  528.   1 index exch
  529.   PDFfile fileposition 3 1 roll
  530.   true resolvestream readfontfilter
  531.         % Stack: filepos fontres stream
  532.   1 index /Subtype get /CIDFontType2 eq {
  533.     .loadttcidfont
  534.         % Stack: filepos fontres cidfont
  535.     1 index /CIDToGIDMap knownoget {
  536.       dup /Identity eq {
  537.     pop
  538.       } {
  539.     true resolvestream
  540.         % The following doesn't work for CIDToGIDMaps with more
  541.         % than 32K-1 entries.  We'll fix it later if necessary.
  542.         % Stack: filepos fontres font mapstream
  543.     dup 2 index /CIDCount oget 2 mul string readstring pop exch closefile
  544.     exch dup length 5 add dict .copydict
  545.     dup /FID undef
  546.     dup /CIDMap 4 -1 roll put
  547.     dup /CIDFontName get exch /CIDFont defineresource
  548.       } ifelse
  549.     } if
  550.   } {
  551.     null 2 index getencoding .loadpdfttfont
  552.   } ifelse
  553.   exch pop
  554.   PDFfile 3 -1 roll setfileposition
  555.         % Ignore both the Encoding and the Widths.
  556.   exch pop
  557. } bdef
  558.  
  559. % ---------------- Type 0 fonts ---------------- %
  560.  
  561. % Predefine the known CMaps, but only create them on demand.
  562. /knownCMaps mark
  563.   /Identity-H { /Identity-H 0 makeIdentityCMap }
  564.   /Identity-V { /Identity-V 1 makeIdentityCMap }
  565. .dicttomark def
  566.  
  567. /makeIdentityCMap {        % <cmapname> <wmode> .makeIdentityCMap -
  568.   .currentglobal true .setglobal 3 1 roll
  569.   /CIDInit /ProcSet findresource begin
  570.   12 dict begin
  571.     begincmap
  572.     /WMode exch def
  573.     /CMapName exch def
  574.     /CIDSystemInfo 3 dict dup begin
  575.       /Registry (Adobe) def
  576.       /Ordering (Japan1) def
  577.       /Supplement 0 def
  578.     end def
  579.     %/CMapName (see above)
  580.     /CMapVersion 1 def
  581.     /CMapType 1 def
  582.     %WMode (see above)
  583.     % The PDF documentation says that these CMaps map CIDs
  584.     % "1 to 65,536".  This is a misprint for 0 to 65,535.
  585.     1 begincodespacerange
  586.     % <0001> <00ff>  <0100> <ffff>
  587.       <0000> <ffff>
  588.     endcodespacerange
  589.     1 begincidrange
  590.     % <0001> <00ff> 1   <0100> <ffff> 256
  591.       <0000> <ffff> 0
  592.     endcidrange
  593.     endcmap
  594.     CMapName currentdict /CMap defineresource
  595.     knownCMaps CMapName 2 index put
  596.   end        % CMap
  597.   end        % CIDInit ProcSet
  598.   exch .setglobal
  599. } bdef
  600.  
  601. /buildType0 {        % <Type0-font-resource> buildType0 <font>
  602.   dup /BaseFont get    % FontName
  603.   1 index /Encoding oget
  604.   dup type /nametype eq {
  605.     dup /CMap resourcestatus {
  606.     pop pop /CMap findresource
  607.     } {
  608.     knownCMaps 1 index .knownget
  609.       { exch pop exec } { /undefined signalerror } ifelse
  610.     } ifelse
  611.   } {
  612.     PDFfile fileposition exch
  613.     dup /CMapName get exch true resolvestream cvx exec
  614.     /CMap findresource
  615.     exch PDFfile exch setfileposition
  616.   } ifelse        % CMap
  617.   [
  618.     3 index /DescendantFonts oget { exec resourcefont } forall
  619.   ]            % subfonts
  620.   composefont
  621.         % Stack: fontres font
  622.   1 index /FontMatrix knownoget {
  623.     dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
  624.       1 index exch makefont exch /FontName get exch definefont
  625.     } {
  626.       pop
  627.     } ifelse
  628.   } if exch pop
  629. } bdef
  630.  
  631. % ---------------- CIDFontType0/2 fonts ---------------- %
  632.  
  633. % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
  634. % arrays and using a (currently very inefficient) CDevProc.
  635. /addCIDmetrics {    % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  636.   dup length 5 add dict .copydict
  637.   dup /FID undef
  638.   dup /UniqueID undef
  639.   dup /XUID undef
  640.     % Insert the widths into the font.
  641.   {W W2 DW DW2} {
  642.     % Stack: pdfresource newfont key
  643.     2 index 1 index .knownget {
  644.       2 index 3 1 roll put
  645.     } {
  646.       pop
  647.     } ifelse
  648.   } forall
  649.   dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  650.   exch pop
  651. } bdef
  652.  
  653. % Apply the [D]W[2] metrics to a character before displaying.
  654. /CIDWProc {        % <w0x> <w0y> <llx> <lly> <urx> <ury>
  655.             %   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
  656.             %   <w0x'> ... <vy'>
  657.   begin
  658.     % Look up and apply [D]W
  659.   10 index
  660.   currentdict /DW .knownget { 1000 div exch pop } if
  661.   currentdict /W .knownget {
  662.     % Search the W array for the CID.
  663.     % ****** NOT IMPLEMENTED YET ******
  664.     pop
  665.   } if
  666.   0 13 2 roll 11 -2 roll pop pop
  667.     % Look up and apply [D]W2
  668.     % ****** NOT IMPLEMENTED YET ******
  669.   pop end
  670. } bdef
  671.  
  672. /buildCIDType0 {    % <CIDFontType0-font-resource> buildCIDType0 <font>
  673.   dup /BaseFont get /CIDFont findresource
  674.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  675. } bdef
  676.  
  677. /buildCIDType2 {    % <CIDFontType2-font-resource> buildCIDType2 <font>
  678.   dup /BaseFont get /CIDFont findresource
  679.   addCIDmetrics dup /BaseFont get exch /CIDFont defineresource
  680. } bdef
  681.  
  682. % ---------------- Other embedded fonts ---------------- %
  683.  
  684. /fontloadprocs mark
  685.   /Type1C /readType1C cvx
  686.   /CIDFontType0C /readCIDFontType0C cvx
  687. .dicttomark readonly def
  688.  
  689. % Read an embedded compressed font.
  690. /readType1C {        % <font-resource> <stream-dict> readType1C <font>
  691.   1 index exch
  692.   PDFfile fileposition 3 1 roll
  693.   dup true resolvestream dup readfontfilter
  694.         % Stack: pos resource streamdict stream filter
  695.   3 index /FontDescriptor oget /FontName oget
  696.   1 index FRD
  697.   closefile closefile pop
  698.   PDFfile 3 -1 roll setfileposition
  699.   /FontDescriptor oget /FontName oget findfont
  700.   adjustfont
  701. } bdef
  702.  
  703. % Read an embedded CFF CIDFont.
  704. /readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
  705.   PDFfile fileposition 3 1 roll
  706.   dup true resolvestream dup readfontfilter
  707.         % Stack: pos resource streamdict stream filter
  708.   3 index /FontDescriptor oget /FontName oget
  709.   1 index FRD
  710.   closefile closefile pop
  711.   PDFfile 3 -1 roll setfileposition
  712.         % Some broken Adobe software produces PDF files in which
  713.         % the FontName of the CFF font and the FontName in the
  714.         % FontDescriptor don't match the BaseFont in the font.
  715.         % Use the FontName, rather than the BaseFont, here.
  716.   dup /FontDescriptor oget /FontName oget /CIDFont findresource
  717.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  718. } bdef
  719.  
  720. % ---------------- Font lookup ---------------- %
  721.  
  722. /fonttypeprocs mark        % <font-resource> -proc- <font>
  723.   /Type0 /buildType0 cvx
  724.   /Type1 /buildType1 cvx
  725.   /MMType1 1 index
  726.   /Type3 /buildType3 cvx
  727.   /TrueType /buildTrueType cvx
  728.   /CIDFontType0 /buildCIDType0 cvx
  729.   /CIDFontType2 /buildCIDType2 cvx
  730. .dicttomark readonly def
  731.  
  732. /resourcefont            % <font-resource> resourcefont <font>
  733.  { dup /PSFont .knownget
  734.     { /FID .knownget { type /fonttype eq } { false } ifelse }
  735.     { false }
  736.    ifelse
  737.     { /PSFont get
  738.     }
  739.     { dup dup /FontDescriptor knownoget
  740.        {    % Stack: font-res font-res font-desc
  741.      dup /FontFile knownoget
  742.       { exch pop readtype1 true }
  743.       { dup /FontFile2 knownoget
  744.          { exch pop readtruetype true }
  745.          { /FontFile3 knownoget
  746.         { dup /Subtype get fontloadprocs exch get exec true }
  747.         { false }
  748.            ifelse
  749.          }
  750.         ifelse
  751.       }
  752.      ifelse
  753.        }
  754.        { false }
  755.       ifelse
  756.         % Stack: font-res font-res false
  757.         %  -or-: font-res font true
  758.       not
  759.        { dup /Subtype get fonttypeprocs exch get exec }
  760.       if
  761.       2 copy /PSFont exch put
  762.       exch pop
  763.     }
  764.    ifelse
  765.  } bdef
  766.  
  767. drawopdict begin
  768.   /d0 {
  769.     .adjustcharwidth setcharwidth
  770.   } bdef
  771.   /d1 {
  772.     6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
  773.   } bdef
  774.   /Tf {
  775.     1 index Page /Font rget not { 1 index /invalidfont signalerror } if
  776.     resourcefont exch Tf pop
  777.   } bdef
  778. end
  779.  
  780. end            % pdfdict
  781. end            % GS_PDF_ProcSet
  782. .setglobal
  783.